package samples

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.yield
import org.junit.Test

/**
 *
 * @author mph
 * @date 2025/1/9
 */
class Context_Dispatcher_Test {

    @Test
    fun test1() = runTest{
        //Unconfined类型的挂起后再次恢复时所在的协程Context由它内部挂起的那个协程所在的Context决定
        //这个不应该在正常开发代码中使用
        launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
            println("Unconfined      : I'm working in thread ${Thread.currentThread().name}")
            delay(500)
            println("Unconfined      : After delay in thread ${Thread.currentThread().name}") //这里会输出delay的Context
            log("End~~")
        }
    }

    @Test
    fun test2() = runTest{
        val request = launch {
            // 传入了一个Job，父协程的取消就无法影响这个子协程了
            launch(Job()) {
                println("job1: I run in my own Job and execute independently!")
                delay(1000)
                println("job1: I am not affected by cancellation of the request")
            }
            // and the other inherits the parent context
            launch {
                delay(100)
                println("job2: I am a child of the request coroutine")
                delay(1000)
                println("job2: I will not execute this line if my parent request is cancelled")
            }
        }
        delay(500)
        request.cancel() // cancel processing of the request
        println("main: Who has survived request cancellation?")
        delay(1000) // delay the main thread for a second to see what happens
    }

    /**
     * 创建CoroutineScope实例
     */
    @Test
    fun test3() = runTest{
        val scope = CoroutineScope(Job())
        val ioScope = CoroutineScope(Dispatchers.IO)
        val mainScope = MainScope() //Dispatchers.MAIN
        scope.launch {
            println("job1: I run in my own context")
            delay(1000)
            println()
        }
        ioScope.launch {
            println("job1: I run in my own context")
            delay(1000)
            println()
        }
        //在UI线程执行
        mainScope.launch {
            println("job1: I run in my own context")
            delay(1000)
            println()
        }
    }

    /**
     * 在协程中设置和传递线程信息
     */
    @Test
    fun test4() = runTest{
        val threadLocal = ThreadLocal<String>()
        threadLocal.set("main")
        println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
        //asContextElement设置协程内的线程信息
        val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) {
            println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
            yield()
            println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
        }
        job.join()
        println("Post-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
    }

}